package com.example.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.apis.article.iArticleClient;
import com.example.model.acl.pojos.Acl_user;
import com.example.model.article.dtos.ArticleDto;
import com.example.model.common.dtos.ResponseResult;
import com.example.model.search.vos.SearchArticleVo;
import com.example.model.tencent.utils.ImageModerationUtil;
import com.example.model.tencent.utils.TextModerationUtil;
import com.example.model.wemedia.pojos.*;
import com.example.user.mapper.AclUserMapper;
import com.example.utils.common.SensitiveWordUtil;
import com.example.wemedia.mapper.*;
import com.example.wemedia.service.WmNewsAutoScanService;
import com.example.wemedia.websocket.WebSocket;
import com.tencentcloudapi.tms.v20201229.models.TextModerationResponse;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private iArticleClient iArticleClient;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private AclUserMapper aclUserMapper;

    @Autowired
    private WebSocket webSocket;

    @Autowired
    private WmMessageMapper wmMessageMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;


    @Override
    @Async
    public void autoScanNews(Integer id) {
        log.info("进入文章审核");
        WmNews wmNews = wmNewsMapper.selectById(id);
        if(wmNews == null){
            throw new RuntimeException("文章不存在");
        }
        Acl_user acl_user = aclUserMapper.selectById(wmNews.getUserId());
        //处于审核状态
        if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
            Map<String, Object> map = handleTextAndImages(wmNews);
            //自管理敏感词过滤
            boolean isSensitive = handleSensitiveScan(map.get("content").toString(),wmNews);
            if(!isSensitive){
                return;
            }
            boolean flagText = handleTextScan(map.get("content").toString(),wmNews);
            boolean flagImage = handleImageScan((List<String>) map.get("images"),wmNews);
//            if(!flagText || !flagImage){
            if(false){
                webSocket.sendMessage("您的名为：【"+wmNews.getTitle()+"】的文章审核失败，原因：含有敏感词汇或者图片");
                WmMessage wmMessage = new WmMessage();
                wmMessage.setUserId(wmNews.getUserId());
                wmMessage.setUserName(acl_user.getName());
                wmMessage.setContent("您的名为：【"+wmNews.getTitle()+"】的文章审核失败，原因：含有敏感词汇或者图片");
                wmMessage.setTime(new Date());
                wmMessageMapper.insert(wmMessage);
                return;
            }
        }
        //审核成功
        ResponseResult responseResult = saveArticle(wmNews,acl_user);
        if(!responseResult.getCode().equals(200)){
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章审核，保存app端相关文章数据失败");
        }
        //回填article_id
        wmNews.setArticleId((responseResult.getData().toString()));
        updateWmNews(wmNews,(short) 9,"审核成功");
        webSocket.sendMessage("您的名为：【"+wmNews.getTitle()+"】的文章审核成功");
        WmMessage wmMessage = new WmMessage();
        wmMessage.setUserId(wmNews.getUserId());
        wmMessage.setUserName(acl_user.getName());
        wmMessage.setContent("您的名为：【"+wmNews.getTitle()+"】的文章审核成功");
        wmMessage.setTime(new Date());
        wmMessageMapper.insert(wmMessage);
        acl_user.setArticleNum(acl_user.getArticleNum()+1);
        aclUserMapper.updateById(acl_user);
    }

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    private boolean handleSensitiveScan(String content, WmNews wmNews) {
        log.info("content {}",content);

        boolean flag = true;
        List<WmSensitive> wmSensitiveList = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
        List<String> strings = wmSensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        log.info("strings {}",strings);
        SensitiveWordUtil.initMap(strings);
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);

        if(map.size() > 0){
            updateWmNews(wmNews,(short) 2,"当前文章存在违规内容"+map);
            flag = false;
        }
        log.info("map content {}",map.toString());

        return flag;
    }

    private ResponseResult saveArticle(WmNews wmNews,Acl_user acl_user) {
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);
        articleDto.setLayout(wmNews.getType());
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if(wmChannel != null){
            articleDto.setChannelName(wmChannel.getName());
        }
        articleDto.setAuthorId(wmNews.getUserId().longValue());
//        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
//        Acl_user aclUser = aclUserMapper.selectById(wmNews.getUserId());
//        if(aclUser != null){
            articleDto.setAuthorName(acl_user.getName());
//        }
        articleDto.setCollection(0);


        //设置作者姓名
        if(wmNews.getArticleId() != null){
            articleDto.setId(wmNews.getArticleId());
        }
        articleDto.setCreatedTime(new Date());
        articleDto.setViews(0);
        articleDto.setLikes(0);
        articleDto.setComment(0);
        articleDto.setLikes(0);


        return iArticleClient.saveArticle(articleDto);
    }

    private boolean handleImageScan(List<String> imageUrls,WmNews wmNews){
        boolean flag = true;
        System.out.println("urls "+imageUrls.toString());
        for (String url : imageUrls){
            if("Block".equals(ImageModerationUtil.uploadText(url).getSuggestion())){
                flag = false;
                wmNews.setStatus((short)2);  //审核失败
                wmNews.setReason("当前文章中存在违规内容");
                wmNewsMapper.updateById(wmNews);
                break;
            }
            else if("Review".equals(ImageModerationUtil.uploadText(url).getSuggestion())){
                flag = false;
                wmNews.setStatus((short)3);  //人工审核
                wmNews.setReason("当前文章中存在不确定内容");
                wmNewsMapper.updateById(wmNews);
                break;
            }

        }
        if(flag){
            wmNews.setStatus((short)1);
        }
        return flag;
    }

    private boolean handleTextScan(String content, WmNews wmNews) {
        if((wmNews.getTitle()+"-"+content).length() == 0){
            return true;
        }
        TextModerationResponse response = TextModerationUtil.uploadText((wmNews.getTitle()+"-"+content));
        if("Block".equals(response.getSuggestion())){
            wmNews.setStatus((short)2);  //审核失败
            wmNews.setReason("当前文章中存在违规内容");
            wmNewsMapper.updateById(wmNews);
            return false;
        }
        if("Review".equals(response.getSuggestion())){
            wmNews.setStatus((short)3);  //人工审核
            wmNews.setReason("当前文章中存在不确定内容");
            wmNewsMapper.updateById(wmNews);
            return false;
        }
        wmNews.setStatus((short)1);
        return true;
    }

    /*
    提取文章和图片
     */
    private Map<String,Object> handleTextAndImages(WmNews wmNews){

        List<String> imageUrls = new ArrayList<>();
        StringBuilder stringBuilder = new StringBuilder();
        if(StringUtils.isNotBlank(wmNews.getContent())){
            List<Map> maps = JSONArray.parseArray(wmNews.getContent(),Map.class);
            for(Map map: maps){
                if("text".equals(map.get("type"))){
                    stringBuilder.append(map.get("value"));
                }
                if("image".equals(map.get("type"))){
                    imageUrls.add((String) map.get("value"));
                }
            }
        }

        Map<String,Object> res = new HashMap<>();
        res.put("content",stringBuilder.toString());
        res.put("images",imageUrls);
        return res;
    }

    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }
}
